package ${package}.${rootArtifactId}.common.util;

import com.google.common.base.Joiner;
import ${package}.${rootArtifactId}.common.exception.ValidateException;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author weidong.lin
 * @description: 校验工具类
 * @date 2019/3/7 17:09
 */
public class ValidatorUtil {
    private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    /**
     * hibernate validator校验
     *
     * @param obj 校验对象
     * @return void
     */
    public static <T> void validate(T obj) {
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(obj);
        List<String> list = new ArrayList<>();
        // 抛出检验异常
        if (constraintViolations.size() > 0) {
            for (ConstraintViolation constraintViolation : constraintViolations) {
                list.add(constraintViolation.getMessage());
            }
        }
        if (list != null && list.size() > 0) {
            throw new ValidateException(Joiner.on(",").skipNulls().join(list));
        }
    }

    /**
     * hibernate validator校验
     *
     * @param obj 校验对象
     * @return 错误信息
     */
    public static <T> String check(T obj) {
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(obj);
        if (null == constraintViolations || constraintViolations.size() == 0) {
            return null;
        }
        int index = 0;
        String[] msgs = new String[constraintViolations.size()];
        for (ConstraintViolation constraintViolation : constraintViolations) {
            msgs[index] = constraintViolation.getMessage();
            index++;
        }
        return Arrays.toString(msgs);
    }

    /**
     * 判断对象是否为空。如果要判断的实例类型为字符串则去除前后空格后验证长度是否为0；如果要判断的实例类型为集合则判断是否为空集；
     * 其他类型则判断是否为null。
     *
     * @param object 要验证的对象。
     * @return 如果为空则返回true；否则返回false。
     */
    public static boolean isEmpty(Object object) {
        if (object == null) {
            return true;
        }

        if (object instanceof String) {
            return ((String) object).trim().length() == 0;
        }

        if (object.getClass().isArray()) {
            return Array.getLength(object) == 0;
        }

        if (object instanceof Iterable) {
            return !((Iterable<?>) object).iterator().hasNext();
        }

        if (object instanceof Map) {
            return ((Map<?, ?>) object).isEmpty();
        }

        return false;
    }

    /**
     * 判断对象是否是非空
     *
     * @param object 要验证的对象
     * @return 如果非空则返回true；否则返回false。
     */
    public static boolean isNotEmpty(Object object) {
        return !isEmpty(object);
    }

    /**
     * 判断对象列表是否存在空
     *
     * @param objArr 要验证的对象列表
     * @return 若没有入参或者存在有一个空，则返回true，全都非空则false。
     */
    public static boolean isAnyEmpty(Object... objArr) {
        if (null == objArr) {
            return true;
        }
        for (Object obj : objArr) {
            if (isEmpty(obj)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断对象列表是否存一个不为空
     *
     * @param objArr 要验证的对象列表
     * @return 判断对象列表是否存一个不为空，则返回true，。
     */
    public static boolean isAnyNotEmpty(Object... objArr) {
        if (null == objArr) {
            return false;
        }
        for (Object obj : objArr) {
            if (!isEmpty(obj)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断对象列表是否不存在空，
     *
     *
     * @param objArr 要验证的对象列表
     * @return 若没有入参或者存在有一个空，则返回false，全都非空则true。
     */
    public static boolean isNoneEmpty(Object... objArr) {
        return !isAnyEmpty(objArr);
    }


    /**
     * 验证byte数组是否以指定byte数组开头。
     *
     * @param bytes  byte数组。
     * @param prefix byte开头。
     * @return 如果是则返回true，否则返回false。
     */
    public static boolean startsWith(byte[] bytes, byte[] prefix) {
        if (isEmpty(bytes) || isEmpty(prefix) || bytes.length < prefix.length) {
            return false;
        }

        for (int i = 0; i < prefix.length; i++) {
            if (bytes[i] != prefix[i]) {
                return false;
            }
        }

        return true;
    }

    /**
     * 校验bean返回map形式的校验结果
     *
     * @param obj bean
     * @return java.util.Map<java.lang.String       ,       java.lang.String>
     */
    public static <T> List<String> validateToList(T obj) {
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(obj);
        List<String> list = new ArrayList<>();
        if (constraintViolations.size() > 0) {
            for (ConstraintViolation constraintViolation : constraintViolations) {
                list.add(constraintViolation.getMessage());
            }
        }
        return list;
    }
}
